#pragma once

#include <algorithm/analytical_model/CommonPara.h>
#include <algorithm/analytical_model/Constants.h>
#include <algorithm/analytical_model/HeliostatPara.h>
#include <algorithm/analytical_model/RectangleGrid.h>
#include <algorithm/analytical_model/ScenePara.h>
#include <algorithm/analytical_model/SimulationPara.h>
#include <algorithm/analytical_model/algorithm/geometry/Utils.h>
#include <algorithm/analytical_model/io/FileTypes.h>
#include <algorithm/shared/data/scene/Heliostat.h>
#include <algorithm/shared/data/scene/Receiver.h>
#include <algorithm/shared/data/scene/Sun.h>

#include <boost/json/value.hpp>

#include <string_view>
#include <variant>
#include <vector>

namespace solar
{
    enum class SimulationOption : char
    {
        Whole,
        PerHeliostat
    };

    struct AnalyticalPipelineParam
    {
            Sun sun_;
            CommonPara common_para_;
            analytical::RectangleGrid rectangle_grid_;
            ScenePara scene_para_;
            SimulationPara simulation_para_;
            std::vector<Heliostat> heliostats_;
            std::vector<Receiver> receivers_;
            std::vector<HeliostatPara> heliostat_paras_;
            ModelType model_type_;
            std::variant<SimplifiedModelType, ConvolutionModelType> detailed_model_type_;
            SimulationOption simulation_option_;
    };

    auto loadAnalyticalPipelineParam(const io::JSONType&,
                                     const std::string_view& file_path) -> AnalyticalPipelineParam;
    auto loadAnalyticalPipelineParam(const io::JSONType&, const boost::json::value& json_value)
        -> AnalyticalPipelineParam;
} // namespace solar
